package top.fangw.gateway.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableReactiveMethodSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.security.web.server.ServerAuthenticationEntryPoint;
import reactor.core.publisher.Mono;
import top.fangw.common.core.result.ResultCode;
import top.fangw.common.oauth.authorization.WebFluxAuthorizationManager;
import top.fangw.gateway.util.ResponseUtils;

/**
 * @author fgw
 * @description
 * @createDate 2024/2/21
 */
@Configuration
@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
public class AuthorizationClientConfig {


    @Bean
    WebFluxAuthorizationManager webFluxAuthorizationManager(){
        return new WebFluxAuthorizationManager();
    }



    @Bean
    public SecurityWebFilterChain authorizationClientSecurityFilterChain(ServerHttpSecurity http) throws Exception {

        //uri放行
        String[] ignoreUrls = new String[]{"/oauth2/**","/*/oauth2/**","/*.html","/favicon.ico","/*/favicon.ico","/webjars/**","/v3/api-docs/swagger-config","/*/v3/api-docs**"};

        //禁用csrf与cors
        http.csrf(ServerHttpSecurity.CsrfSpec::disable);
        http.cors(ServerHttpSecurity.CorsSpec::disable);
        //客户端设置
        http
                .authorizeExchange(authorize ->
                        authorize.pathMatchers(ignoreUrls).permitAll()
//                                .anyExchange().authenticated()
                                // 鉴权管理器配置
                                .anyExchange().access(webFluxAuthorizationManager())
                );

        return http.build();
    }


    /**
     * token无效或者已过期自定义响应
     */
    @Bean
    ServerAuthenticationEntryPoint authenticationEntryPoint() {
        return (exchange, e) -> {
            Mono<Void> mono = Mono.defer(() -> Mono.just(exchange.getResponse()))
                    .flatMap(response -> ResponseUtils.writeErrorInfo(response, ResultCode.TOKEN_INVALID_OR_EXPIRED));
            return mono;
        };
    }



}
